package com.huike.framework.aspectj;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
import com.huike.clues.domain.SysOperLog;
import com.huike.clues.mapper.SysOperLogMapper;
import com.huike.common.core.domain.AjaxResult;
import com.huike.common.core.domain.entity.SysUserDTO;
import com.huike.common.core.domain.model.LoginUser;
import com.huike.common.utils.ServletUtils;
import com.huike.common.utils.ip.AddressUtils;
import com.huike.common.utils.spring.SpringUtils;
import com.huike.framework.web.service.TokenService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;

/**
 * 用户操作日志
 *
 * @Author Ls
 * @Date 2025/10/27 10:21
 */
@Slf4j
@Aspect
@Component
public class LoginInforAspect  {

    @Autowired
    private SysOperLogMapper operLogMapper;

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Around("execution(* com.huike.web.controller.clues.TbCourseController.*(..)) && @annotation(com.huike.common.annotation.UserLog)")
    public Object UserLog(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = null;

        try {
            //运行方法得到返回值
            result = joinPoint.proceed();
            return result;
        } finally {
            //将返回值转换为JSON字符串
            String jsonResult = JSONUtil.toJsonStr(result);

            //根据连接点得到签名对象
            Signature signature = joinPoint.getSignature();

            //获取方法所在类的全类名名
            String method = joinPoint.getTarget().getClass().getName();
            //从签名对象中获取方法名
            String name = signature.getName();
            method = method + "." + name + "()";

            //获取模块名
            String title = "";
            Api annotation = joinPoint.getTarget().getClass().getAnnotation(Api.class);
            if (annotation != null){
                String[] tags = annotation.tags();
                if (ArrayUtil.isNotEmpty(tags)){
                    title = tags[0];
                }
            }

            //获取HTTP请求对象
            HttpServletRequest request = ServletUtils.getRequest();
            //从请求对象中获取请求方法（GET，POST。。。）
            String requestMethod = request.getMethod();
            String url = request.getRequestURI();

            String businessType = "";
            //根据请求类型，获取业务类型（删除，新增。。）转换为数据库中对应的值
            switch (requestMethod){
                case "POST":
                    businessType = "1";
                    break;
                case "PUT":
                    businessType = "2";
                    break;
                case "DELETE":
                    businessType = "3";
                    break;
                default:
                    businessType = "0";
            }
            //获取HTTP响应对象
            HttpServletResponse response = ServletUtils.getResponse();
            //获取响应的状态码
            Integer status = response.getStatus() == 200?0:1;

            // 获取当前的用户
            LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
            //根据IP获取操作地点
            String address = AddressUtils.getRealAddressByIP(loginUser.getIpaddr());
            //从登录的用户中获取详细的用户信息
            SysUserDTO user = loginUser.getUser();

            //获取请求参数
            String jsonParams = JSONUtil.toJsonStr(joinPoint.getArgs());

            //获取返回的提示信息
            AjaxResult ajaxResult = JSONUtil.toBean(jsonResult, AjaxResult.class);
            String msg = ajaxResult.getMsg();

            String finalTitle = title;
            String finalBusinessType = businessType;
            String finalMethod = method;
            threadPoolTaskExecutor.submit(() -> {
                //组装数据
                SysOperLog sysOperLog = SysOperLog.builder()
                        .title(finalTitle)
                        .businessType(Integer.parseInt(finalBusinessType))
                        .method(finalMethod)
                        .requestMethod(requestMethod)
                        .operatorType(1)
                        .operName(user.getUserName())
                        .deptName(user.getDept().getDeptName())
                        .operUrl(url)
                        .operIp(loginUser.getIpaddr())
                        .operLocation(address)
                        .operParam(jsonParams)
                        .jsonResult(jsonResult)
                        .status(status)
                        .errorMsg(msg)
                        .operTime(new Date())
                        .build();

                operLogMapper.insert(sysOperLog);
            });

        }

    }


}
